﻿#pragma once
#include "JsonSetting.h"

static std::map<std::string, std::string> MaskEffectFile{
    {"fade", "./../Effects/fade.svg"},
    {"outside_circle", "./../Effects/circle_in_to_out.svg"},
    {"inside_circle", "./../Effects/circle_out_to_in.svg"},
    {"wipe_bottom_to_top", "./../Effects/wipe_bottom_to_top.svg"},
    {"wipe_left_to_right", "./../Effects/wipe_left_to_right.svg"},
    {"wipe_right_to_left", "./../Effects/wipe_right_to_left.svg"},
    {"wipe_top_to_bottom", "./../Effects/wipe_top_to_bottom.svg"}
};

class GlobalData
{
public:
    static std::shared_ptr<GlobalData> GetGlobalData()
    {
        if(!GlobalInstance)
        {
            GlobalInstance = std::make_shared<GlobalData>(GlobalData());
        }
        return GlobalInstance;
    }

    int GetVideoWidth(){ return VideoWidth; }
    int GetVideoHeight(){ return VideoHeight; }
    float GetFps(){ return Fps; }
    int GetVideoBitRate(){ return VideoBitRate; }
    int GetAudioSampleRate(){ return AudioSampleRate; }
    int GetAudioBitRate(){ return AudioBitRate; }
    int GetAudioChannels(){ return AudioChannels; }
    openshot::ChannelLayout GetAudioChannelLayout(){ return AudioChannelLayout; }

    void SetVideoWidth(int Width){ VideoWidth = Width; }
    void SetVideoHeight(int Height){ VideoHeight = Height; }
    void SetFps(float InFps){ Fps = InFps; }
    void SetVideoBitRate(int BitRate){ VideoBitRate = BitRate; }
    void SetAudioSampleRate(int SampleRate){ AudioSampleRate = SampleRate; }
    void SetAudioBitRate(int BitRate){ AudioBitRate = BitRate; }
    void SetAudioChannels(int Channels){ AudioChannels = Channels; }
    void SetAudioChannelLayout(openshot::ChannelLayout Layout){ AudioChannelLayout = Layout; }

private:
    GlobalData() : VideoWidth(3840), VideoHeight(2160), Fps(30), VideoBitRate(3000000), AudioSampleRate(44100), AudioBitRate(128000), AudioChannels(2), AudioChannelLayout(openshot::LAYOUT_STEREO){}

    static std::shared_ptr<GlobalData> GlobalInstance;
    int VideoWidth;
    int VideoHeight;
    float Fps;
    int VideoBitRate;
    int AudioSampleRate;
    int AudioBitRate;
    int AudioChannels;
    openshot::ChannelLayout AudioChannelLayout;
};

class JsonVideoClip
{
public:
    JsonVideoClip(){}
    ~JsonVideoClip();
    JsonVideoClip(const Json::Value& JsonInfo);
    
    JsonVideoClip(const JsonVideoClip& SrcData)
    {
        JsonVideoClipArray.reserve(SrcData.JsonVideoClipArray.size());
        for (VideoClipInfo* ClipInfo : SrcData.JsonVideoClipArray)
        {
            VideoClipInfo* NewClipInfo = new VideoClipInfo(*ClipInfo);
            JsonVideoClipArray.push_back(NewClipInfo);
        }
    }
    
    JsonVideoClip& operator=(const JsonVideoClip& SrcData)
    {
        if (this != &SrcData)
        {
            JsonVideoClipArray.clear();
            JsonVideoClipArray.reserve(SrcData.JsonVideoClipArray.size());
            for (VideoClipInfo* ClipInfo : SrcData.JsonVideoClipArray)
            {
                VideoClipInfo* NewClipInfo = new VideoClipInfo(*ClipInfo);
                JsonVideoClipArray.push_back(NewClipInfo);
            }
        }
        return *this;
    }

public:
    struct VideoClipInfo
    {
        std::string Name = "";
        std::string File = "";
        int Layer = 0;
        std::string StartTimeFunc = "";
        std::string FinishTimeFunc = "";
        std::string ZoomRateFunc = "";
        float PositionTime = 0.0f;
        float BeginTime = 0.0f;
        float EndTime = 0.0f;
        float ZoomRate = 1.0f;
        int Width = 1920;
        int Height = 1080;
        float Fps = 30.0f;
        int VideoFrame = 0;
        bool Hasvideo = true;
        bool HasAudio = true;
    };
    
    std::vector<VideoClipInfo*> JsonVideoClipArray;
};

class JsonAudioClip
{
public:
    JsonAudioClip(){}
    ~JsonAudioClip();
    JsonAudioClip(const Json::Value& JsonInfo);

    JsonAudioClip(const JsonAudioClip& SrcData)
    {
        JsonAudioClipArray.reserve(SrcData.JsonAudioClipArray.size());
        for (AudioClipInfo* ClipInfo : SrcData.JsonAudioClipArray)
        {
            AudioClipInfo* NewClipInfo = new AudioClipInfo(*ClipInfo);
            JsonAudioClipArray.push_back(NewClipInfo);
        }
    }
    
    JsonAudioClip& operator=(const JsonAudioClip& SrcData)
    {
        if (this != &SrcData)
        {
            JsonAudioClipArray.clear();
            JsonAudioClipArray.reserve(SrcData.JsonAudioClipArray.size());
            for (AudioClipInfo* ClipInfo : SrcData.JsonAudioClipArray)
            {
                AudioClipInfo* NewClipInfo = new AudioClipInfo(*ClipInfo);
                JsonAudioClipArray.push_back(NewClipInfo);
            }
        }
        return *this;
    }
    
public:
    struct AudioClipInfo
    {
        std::string Name = "";
        std::string File = "";
        int Layer = 0;
        std::string StartTimeFunc = "";
        std::string FinishTimeFunc = "";
        std::string ZoomRateFunc = "";
        float PositionTime = 0.0f;
        float BeginTime = 0.0f;
        float EndTime = 0.0f;
        float ZoomRate = 1.0f;
        int AudioFrame = 0;
        // int SampleRate = 44100;
        // int Channels = 2;
        // ChannelLayout ChannelLayout = LAYOUT_STEREO;
        bool HasAudio = true;
    };
    
    std::vector<AudioClipInfo*> JsonAudioClipArray;
};

class JsonVideoEffectClip
{
public:
    JsonVideoEffectClip(){}
    ~JsonVideoEffectClip();
    JsonVideoEffectClip(const Json::Value& JsonInfo);

    JsonVideoEffectClip(const JsonVideoEffectClip& SrcData)
    {
        JsonVideoEffectClipArray.reserve(SrcData.JsonVideoEffectClipArray.size());
        for (VideoEffectClipInfo* ClipInfo : SrcData.JsonVideoEffectClipArray)
        {
            VideoEffectClipInfo* NewClipInfo = new VideoEffectClipInfo(*ClipInfo);
            JsonVideoEffectClipArray.push_back(NewClipInfo);
        }
    }
    
    JsonVideoEffectClip& operator=(const JsonVideoEffectClip& SrcData)
    {
        if (this != &SrcData)
        {
            JsonVideoEffectClipArray.clear();
            JsonVideoEffectClipArray.reserve(SrcData.JsonVideoEffectClipArray.size());
            for (VideoEffectClipInfo* ClipInfo : SrcData.JsonVideoEffectClipArray)
            {
                VideoEffectClipInfo* NewClipInfo = new VideoEffectClipInfo(*ClipInfo);
                JsonVideoEffectClipArray.push_back(NewClipInfo);
            }
        }
        return *this;
    }
    
public:
    struct VideoEffectClipInfo
    {
        std::string Name = "";
        std::string File = "";
        int Layer = 0;
        std::string StartTimeFunc = "";
        std::string FinishTimeFunc = "";
        std::string ZoomRateFunc = "";
        float PositionTime = 0.0f;
        float BeginTime = 0.0f;
        float EndTime = 0.0f;
        float ZoomRate = 1.0f;
        float VideoLenghtRate = 1.0f;
        int VideoFrame = 0;
        int Width = 1920;
        int Height = 1080;
        float Fps = 30.0f;
        bool IsRepeat = false;
        bool Hasvideo = true;
        bool HasAudio = true;
        float CoordX = 0;
        float CoordY = 0;
        float ScaleX = 1;
        float ScaleY = 1;
        int Rotation = 0;
        float Alpha = 1;
    };
    
    std::vector<VideoEffectClipInfo*> JsonVideoEffectClipArray;
};

class JsonMaskEffect
{
public:
    JsonMaskEffect(){}
    ~JsonMaskEffect();
    JsonMaskEffect(const Json::Value& JsonInfo);

    JsonMaskEffect(const JsonMaskEffect& SrcData)
    {
        JsonMaskEffectArray.reserve(SrcData.JsonMaskEffectArray.size());
        for (MaskEffectInfo* ClipInfo : SrcData.JsonMaskEffectArray)
        {
            MaskEffectInfo* NewClipInfo = new MaskEffectInfo(*ClipInfo);
            JsonMaskEffectArray.push_back(NewClipInfo);
        }
    }
    
    JsonMaskEffect& operator=(const JsonMaskEffect& SrcData)
    {
        if (this != &SrcData)
        {
            JsonMaskEffectArray.clear();
            JsonMaskEffectArray.reserve(SrcData.JsonMaskEffectArray.size());
            for (MaskEffectInfo* ClipInfo : SrcData.JsonMaskEffectArray)
            {
                MaskEffectInfo* NewClipInfo = new MaskEffectInfo(*ClipInfo);
                JsonMaskEffectArray.push_back(NewClipInfo);
            }
        }
        return *this;
    }
    
public:
    struct MaskEffectInfo
    {
        std::string Type = "";
        std::string Name = "";
        std::string File = "";
        bool TransitionIn = true;
        int Layer = 0;
        std::string StartTimeFunc = "";
        std::string FinishTimeFunc = "";
        std::string ZoomRateFunc = "";
        float PositionTime = 0.0f;
        float BeginTime = 0.0f;
        float EndTime = 0.0f;
        float ZoomRate = 1.0f;
    };
    
    std::vector<MaskEffectInfo*> JsonMaskEffectArray;
};

class JsonImageEffect
{
public:
    JsonImageEffect(){}
    ~JsonImageEffect();
    JsonImageEffect(const Json::Value& JsonInfo);

    JsonImageEffect(const JsonImageEffect& SrcData)
    {
        JsonImageEffectArray.reserve(SrcData.JsonImageEffectArray.size());
        for (ImageEffectInfo* ClipInfo : SrcData.JsonImageEffectArray)
        {
            ImageEffectInfo* NewClipInfo = new ImageEffectInfo(*ClipInfo);
            JsonImageEffectArray.push_back(NewClipInfo);
        }
    }
    
    JsonImageEffect& operator=(const JsonImageEffect& SrcData)
    {
        if (this != &SrcData)
        {
            JsonImageEffectArray.clear();
            JsonImageEffectArray.reserve(SrcData.JsonImageEffectArray.size());
            for (ImageEffectInfo* ClipInfo : SrcData.JsonImageEffectArray)
            {
                ImageEffectInfo* NewClipInfo = new ImageEffectInfo(*ClipInfo);
                JsonImageEffectArray.push_back(NewClipInfo);
            }
        }
        return *this;
    }
    
public:
    struct ImageEffectInfo
    {
        std::string Type = "";
        std::string Name = "";
        std::string File = "";
        int Layer = 2;
        std::string StartTimeFunc = "";
        std::string FinishTimeFunc = "";
        std::string ZoomRateFunc = "";
        int VideoFrame = 0;
        float PositionTime = 0.0f;
        float BeginTime = 0.0f;
        float EndTime = 0.0f;
        float ZoomRate = 1.0f;
        float CoordX = 0;
        float CoordY = 0;
        float ScaleX = 1;
        float ScaleY = 1;
        int Rotation = 0;
        float Alpha = 1;
    };
    
    std::vector<ImageEffectInfo*> JsonImageEffectArray;
};

class JsonFontEffect
{
public:
    JsonFontEffect(){}
    ~JsonFontEffect();
    JsonFontEffect(const Json::Value& JsonInfo);

    JsonFontEffect(const JsonFontEffect& SrcData)
    {
        JsonFontEffectArray.reserve(SrcData.JsonFontEffectArray.size());
        for (FontEffectInfo* ClipInfo : SrcData.JsonFontEffectArray)
        {
            FontEffectInfo* NewClipInfo = new FontEffectInfo(*ClipInfo);
            JsonFontEffectArray.push_back(NewClipInfo);
        }
    }
    
    JsonFontEffect& operator=(const JsonFontEffect& SrcData)
    {
        if (this != &SrcData)
        {
            JsonFontEffectArray.clear();
            JsonFontEffectArray.reserve(SrcData.JsonFontEffectArray.size());
            for (FontEffectInfo* ClipInfo : SrcData.JsonFontEffectArray)
            {
                FontEffectInfo* NewClipInfo = new FontEffectInfo(*ClipInfo);
                JsonFontEffectArray.push_back(NewClipInfo);
            }
        }
        return *this;
    }
    
public:
    struct FontEffectInfo
    {
        std::string Type = "";
        std::string Name = "";
        std::string Text = "";
        int FontSize = 0;
        std::string FontFile = "";
        std::string FontType = "";
        std::string Color = "#ff000000";
        std::string StrokeColor = "00ff0000";
        float StrokeWidth = 1.0f;
        int Layer = 0;
        std::string StartTimeFunc = "";
        std::string FinishTimeFunc = "";
        std::string ZoomRateFunc = "";
        float PositionTime = 0.0f;
        float BeginTime = 0.0f;
        float EndTime = 0.0f;
        float ZoomRate = 1.0f;
        float CoordX = 0;
        float CoordY = 0;
        float Alpha = 1;
    };
    
    std::vector<FontEffectInfo*> JsonFontEffectArray;
};

class JsonShotCutCaption
{
public:
    JsonShotCutCaption(){}
    ~JsonShotCutCaption();
    JsonShotCutCaption(const Json::Value& JsonInfo);

    JsonShotCutCaption(const JsonShotCutCaption& SrcData)
    {
        JsonCaptionInfoArray.reserve(SrcData.JsonCaptionInfoArray.size());
        for (CaptionInfo* ClipInfo : SrcData.JsonCaptionInfoArray)
        {
            CaptionInfo* NewClipInfo = new CaptionInfo(*ClipInfo);
            JsonCaptionInfoArray.push_back(NewClipInfo);
        }
    }
    
    JsonShotCutCaption& operator=(const JsonShotCutCaption& SrcData)
    {
        if (this != &SrcData)
        {
            JsonCaptionInfoArray.clear();
            JsonCaptionInfoArray.reserve(SrcData.JsonCaptionInfoArray.size());
            for (CaptionInfo* ClipInfo : SrcData.JsonCaptionInfoArray)
            {
                CaptionInfo* NewClipInfo = new CaptionInfo(*ClipInfo);
                JsonCaptionInfoArray.push_back(NewClipInfo);
            }
        }
        return *this;
    }
    
public:
    struct CaptionInfo
    {
        std::string Name = "";
        std::string Text = "";
        int FontSize = 0;
        std::string FontFile = "";
        std::string FontType = "";
        float Rate = 1;
        std::string Color = "#ff000000";
        std::string StrokeColor = "00ff0000";
        float StrokeWidth = 1.0f;
        int Layer = 0;
        std::string StartTimeFunc = "";
        std::string FinishTimeFunc = "";
        std::string ZoomRateFunc = "";
        float PositionTime = 0.0f;
        float BeginTime = 0.0f;
        float EndTime = 0.0f;
        float ZoomRate = 1.0f;
        float CoordX = 0;
        float CoordY = 0;
        float Alpha = 1;
    };
    
    std::vector<CaptionInfo*> JsonCaptionInfoArray;
};
